package com.cmc.cloud.cmclink.doc.service.impl.approvespace;

import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import com.cmc.cloud.cmclink.doc.constants.errorconstant.SoApproveSpaceErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.dto.RestoreSpace;
import com.cmc.cloud.cmclink.doc.entity.SoCargoDO;
import com.cmc.cloud.cmclink.doc.entity.SoForecastDO;
import com.cmc.cloud.cmclink.doc.entity.VoyageBsaCbaDO;
import com.cmc.cloud.cmclink.doc.service.VoyageBsaCbaService;
import com.cmc.cloud.cmclink.doc.service.approvespace.AutoSpaceService;
import com.cmc.cloud.cmclink.doc.service.so.SoCargoService;
import com.cmc.cloud.cmclink.doc.service.so.SoForecastService;
import com.cmc.cloud.cmclink.doc.task.SoAutoApproveSpace;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 自动批舱impl
 *
 * @author dev89
 */
@Service
@Validated
@Slf4j
public class AutoSpaceServiceImpl implements AutoSpaceService {
    @Resource
    private SoForecastService soForecastService;

    @Resource
    private SoCargoService soCargoService;

    @Resource
    private VoyageBsaCbaService voyageBsaCbaService;

    @Override
    public void restoreAllocatedSpace(List<RestoreSpace> restoreSpaceList) {
        if (CollectionUtils.isEmpty(restoreSpaceList)) {
            return;
        }
        log.info("restoreAllocatedSpace, {}", restoreSpaceList);
        List<Long> soIds = restoreSpaceList.stream().map(RestoreSpace::getSoId).collect(Collectors.toList());
        List<SoForecastDO> soForecastDoList = soForecastService.seleteBySoIdList(soIds);
        Map<Long, SoCargoDO> cargoListMap = soCargoService.selectBySoIds(soIds);

        // 计算SO所需TEU,冷插数RF Map<soId, teu数量> <soId, rfUnit数量>
        Map<Long, Integer> soTeuMap = new HashMap<>(16);
        Map<Long, Integer> soRfMap = new HashMap<>(16);
        SoAutoApproveSpace.transferSoTeu(soForecastDoList, soTeuMap, soRfMap, cargoListMap);

        Set<Long> allocationIds = new HashSet<>();
        restoreSpaceList.forEach(space -> allocationIds.addAll(space.getAllocationIds()));
        List<VoyageBsaCbaDO> voyageBsaCbaDOList = voyageBsaCbaService.getVoyageBsaCbaList(allocationIds);
        Map<Long, VoyageBsaCbaDO> voyageBsaCbaMap =
            voyageBsaCbaDOList.stream().collect(Collectors.toMap(VoyageBsaCbaDO::getId, obj -> obj));
        for (RestoreSpace restoreSpace : restoreSpaceList) {
            Long soId = restoreSpace.getSoId();
            List<Long> allocationIdTmps = restoreSpace.getAllocationIds();
            allocationIdTmps.forEach(id -> {
                if (!voyageBsaCbaMap.containsKey(id)) {
                    throw ServiceExceptionUtil.exception(SoApproveSpaceErrorCodeConstants.VOYAGE_BSA_CBA_NOT_EXIST);
                }
                restoreRemainTeuAndRf(soTeuMap, soRfMap, voyageBsaCbaMap.get(id), soId);
            });
        }

        voyageBsaCbaService.updateBatchVoyageBsaCba(voyageBsaCbaDOList);
    }

    private void restoreRemainTeuAndRf(Map<Long, Integer> soTeuMap, Map<Long, Integer> soRfMap, VoyageBsaCbaDO bsa,
        Long soId) {
        int soTeu = soTeuMap.getOrDefault(soId, 0);
        int soRf = soRfMap.getOrDefault(soId, 0);
        int remainTeu = bsa.getRemainAllocationSpace();
        int remainRf = bsa.getRemainRfUnit();
        remainTeu += soTeu;
        remainRf += soRf;
        if (remainTeu > bsa.getAllocationSpace() || remainRf > bsa.getRfUnit()) {
            throw ServiceExceptionUtil.exception(SoApproveSpaceErrorCodeConstants.TEU_OR_RF_LARGER_THAN_ALL);
        }
        bsa.setRemainAllocationSpace(remainTeu);
        bsa.setRemainRfUnit(remainRf);
    }
}
